import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;
import javax.swing.JFrame;

public class myDriver 
{
	private static File textFile = null;
	private static File nfaFile = null;
	protected static int counter = 0; //counter for state 1
	protected static JFrame frame;
	private static NFA myNFA = null;
	private static State startState = null; 
	private static ArrayList<State> currentStates = new ArrayList<State>();
	private static ArrayList<State> nfaStates = new ArrayList<State>();
	private static HashMap<State, List<Transition>> nfaTable = new HashMap<State, List<Transition>>();
	private static int maxClones = 0;
	private static int totTransitions = 0;

	public static void main(String[] args)
	{
		//MY VARIABLES
		boolean run = true;
		int state = 0;
		myScanner myPanel = new myScanner();
		int state2counter = 0;
		//END OF VARIABLES
		
		while(run == true)
		{
			//console scanner
			String cmd = null;  // Declare a variable to hold the name.
	        Scanner in = new Scanner(System.in);
	        
			if (state == 0)    //get command state
			{
		        System.out.println("Current State: 0 - Options: quit or help or next");
		        System.out.print("Input Command: ");
		        cmd = in.nextLine();      // Read one line from the console.
		        System.out.println();
		        
		        if(cmd.equals("quit"))
		        {
		        	System.out.println("Terminating. Bye!");
		        	run = false;
		        }
		        else if(cmd.equals("help"))
		        {
		        	System.out.println("Type in: next or help or quit");
		        }
		        else if(cmd.equals("next"))
		        {
		        	state = 1;
		        }
			}
			else if (state ==1)
			{
				if (counter ==0)
				{
					System.out.print("Current State: 1 - GUI for nfa file: ");
					frame = new JFrame("Let's get our nfa file");

			        frame.add(myPanel);

			        frame.pack();
			        frame.setVisible(true);
			        counter = 3; //random place so the counter cannot reached
				}
				
				if(counter == 1)
				{
					nfaFile = myPanel.getFile();
					counter++; //no longer in counter 1
				}
				
				if(nfaFile != null)
				{
					System.out.println("NFA file name is "+nfaFile.getName());
					state = 2;
				}
			}
			else if (state == 2)
			{
				if(state2counter == 0)
				{
					System.out.println("Current State: 2 - Processing NFA File");
					myNFA = new NFA(nfaFile);
					nfaTable = myNFA.getTable();
					nfaStates = myNFA.getStates();
					startState = myNFA.getStartState();
					currentStates.add(startState); //to begin
				}
				state = 3;
				counter = 0;
			}
			else if(state ==3)  
			{
				if (counter ==0)
				{
					System.out.print("Current State: 3 - GUI for input file: ");
					frame = new JFrame("Let's get our input file");

			        frame.add(myPanel);

			        frame.pack();
			        frame.setVisible(true);
			        counter = 3; //random place so the counter cannot reached
				}
				
				if(counter == 1)
				{
					textFile = myPanel.getFile();
					counter++; //no longer in 1
				}
				
				if(textFile != null)
				{
					System.out.println("Input file name is "+textFile.getName());
					state = 4;
				}
			}
			else if(state ==4) //Reading through the input text a character at a time and consult with NFA
			{
				System.out.println("Current State: 4 - Processing and Generating output text file ");
				int ch;
				StringBuffer strContent = new StringBuffer("");
				FileInputStream fin = null;
				
				try{
					FileWriter outFile = new FileWriter("nfaOutput.txt");
					PrintWriter out = new PrintWriter(outFile);
					
					try
				    {
						int count = 0;
						fin = new FileInputStream(textFile);
						while( (ch = fin.read()) != -1)
						{	
							if(ch ==32) //ignore space
							{
								continue;
								
							}
							System.out.println("Current Input is: " + Character.toString((char)ch));
							
							//keep track of the current state
							if (currentStates.size() == 1)
							{
								if(nfaTable.get(currentStates.get(0)) != null)
								{
									if(next((char)ch, nfaTable.get(currentStates.get(0))) != null)
									{
										currentStates = next((char)ch, nfaTable.get(currentStates.get(0)));
										totTransitions++;
									}
									//else stay in the same transition
								}
							}
							else if (currentStates.size() > 1)
							{								
								if (currentStates.size() > maxClones)
								{
									maxClones = currentStates.size();
								}
								
								ArrayList<State> tempAll = new ArrayList<State>();
								
								for(int i = 0; i < currentStates.size(); i++)
								{
									if(nfaTable.get(currentStates.get(i)) != null)
									{
										if (next((char)ch, nfaTable.get(currentStates.get(i))) != null)
										{
											ArrayList<State> temp  = next((char)ch, nfaTable.get(currentStates.get(i)));
											totTransitions += temp.size();
											tempAll.addAll(temp);
										}
										else
										{
											tempAll.add(currentStates.get(i));
										}
									}
								}
								
								if(tempAll.size() > 0)
								{
									currentStates = tempAll;
								}			
							}
							else
								System.out.println("current state size is" + currentStates.size());
							
							if(count == 0)
							{
								out.println("TOKENS");
								count++;
							}
							
							if(currentStates.size() > 0)
							{
								for(int i = 0; i < currentStates.size(); i++)
								{
									if(currentStates.get(i).accept())
									{
										System.out.println(currentStates.get(i).getToken());
										strContent.append(currentStates.get(i).getToken() + " "+ currentStates.get(i).getName());
										out.println(strContent);
										strContent = new StringBuffer(""); //clear for the next
										currentStates.clear();
										currentStates.add(startState); //go back to the starting state
									}
								}
							}
						}
						System.out.println("The total number of transitions performed: " + totTransitions);
						System.out.println("The maximum number of clones: " + maxClones);
						out.println();
						out.println("The total number of transitions performed: " + totTransitions);
						out.println("The maximum number of clones: " + maxClones);
						out.close();
				    }
					catch(FileNotFoundException e)
				    {
				      System.out.println("cant find");
				    } catch (IOException e) 
				    {
						e.printStackTrace();
					}
					
				} catch (IOException e)
				{
					e.printStackTrace();
				}
				
				state = 0; // go back to the beginning
			}//end state 4
		}//end while run true
	}//end public main
	
	
	/*
	 * getting a current state's list of transitions along with the input
	 */
	public static ArrayList<State> next(Character input, List<Transition> transitions)
	{
		for(int i = 0; i < transitions.size(); i++)
		{
			Matcher temp = transitions.get(i).getInput();
			if(temp.accepts(input)) //accepts the input so this is the transition we want
			{
				return transitions.get(i).getStates();
			}
		}
		System.out.println("No next state exists in the NFA table with given input");
		return null;
	}
}